import { message } from 'antd';
import { tokenManager } from '@/services/apiClient';
import type { 
  StreamStartRequestSerializer,
  StreamStartResponseSerializer,
  StreamChunkResponseSerializer,
  StreamCompleteResponseSerializer,
  StreamErrorResponseSerializer,
  StreamStopRequestSerializer,
  StreamStoppedResponseSerializer,
  PingRequestSerializer,
  PongResponseSerializer,
} from '@/services/generated';

interface ChatWebSocketConfig {
  conversationId: number;
  onMessage?: (data: any) => void;
  onStreamStart?: (data: StreamStartResponseSerializer) => void;
  onStreamChunk?: (data: StreamChunkResponseSerializer) => void;
  onStreamComplete?: (data: StreamCompleteResponseSerializer) => void;
  onStreamError?: (data: StreamErrorResponseSerializer) => void;
  onStreamStopped?: (data: StreamStoppedResponseSerializer) => void;
  onPong?: (data: PongResponseSerializer) => void;
  onConnect?: () => void;
  onDisconnect?: () => void;
  onError?: (error: Event) => void;
}

export class ChatWebSocketService {
  private ws: WebSocket | null = null;
  private config: ChatWebSocketConfig;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 1000;
  private heartbeatInterval: NodeJS.Timeout | null = null;
  private heartbeatIntervalMs = 30000; // 30秒心跳

  constructor(config: ChatWebSocketConfig) {
    this.config = config;
  }

  connect(): void {
    try {
      // 从全局配置获取后端地址
      const apiBasePath = (window as any).APP_CONFIG?.API_BASE_PATH || 'http://localhost:8000';
      
      // 将HTTP(S)协议转换为WebSocket协议
      const wsUrl = apiBasePath.replace(/^https?:/, apiBasePath.startsWith('https:') ? 'wss:' : 'ws:');
      const token = tokenManager.getToken();
      
      // 构建完整的WebSocket URL，将token作为查询参数添加到URL中
      const fullWsUrl = `${wsUrl}/ws/ai-chat/conversations/${this.config.conversationId}/stream/${token ? `?token=${encodeURIComponent(token)}` : ''}`;
      
      console.log('WebSocket连接URL:', fullWsUrl.replace(/token=[^&]+/, 'token=***'));
      
      this.ws = new WebSocket(fullWsUrl);
      
      this.ws.onopen = this.handleOpen.bind(this);
      this.ws.onmessage = this.handleMessage.bind(this);
      this.ws.onclose = this.handleClose.bind(this);
      this.ws.onerror = this.handleError.bind(this);
    } catch (error) {
      console.error('WebSocket连接失败:', error);
      this.config.onError?.(error as Event);
    }
  }

  disconnect(): void {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
    
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }

  private handleOpen(): void {
    console.log('WebSocket连接已建立');
    this.reconnectAttempts = 0;
    this.config.onConnect?.();
    this.startHeartbeat();
  }

  private handleMessage(event: MessageEvent): void {
    try {
      const data = JSON.parse(event.data);
      console.log('收到WebSocket消息:', data);
      
      // 通用消息回调
      this.config.onMessage?.(data);
      
      // 根据消息类型分发到对应的回调
      switch (data.type) {
        case 'stream_start':
          this.config.onStreamStart?.(data as StreamStartResponseSerializer);
          break;
        case 'stream_chunk':
          this.config.onStreamChunk?.(data as StreamChunkResponseSerializer);
          break;
        case 'stream_complete':
          this.config.onStreamComplete?.(data as StreamCompleteResponseSerializer);
          break;
        case 'stream_error':
          this.config.onStreamError?.(data as StreamErrorResponseSerializer);
          break;
        case 'stream_stopped':
          this.config.onStreamStopped?.(data as StreamStoppedResponseSerializer);
          break;
        case 'pong':
          this.config.onPong?.(data as PongResponseSerializer);
          break;
        default:
          console.warn('未知的消息类型:', data.type);
      }
    } catch (error) {
      console.error('解析WebSocket消息失败:', error);
    }
  }

  private handleClose(event: CloseEvent): void {
    console.log('WebSocket连接已关闭:', event.code, event.reason);
    this.config.onDisconnect?.();
    
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }

    // 自动重连逻辑（除非是正常关闭）
    if (event.code !== 1000 && this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1); // 指数退避
      console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})，${delay}ms后重试`);
      
      setTimeout(() => {
        this.connect();
      }, delay);
    } else if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      message.error('WebSocket连接失败，请刷新页面重试');
    }
  }

  private handleError(event: Event): void {
    console.error('WebSocket错误:', event);
    this.config.onError?.(event);
  }

  private startHeartbeat(): void {
    this.heartbeatInterval = setInterval(() => {
      this.sendPing();
    }, this.heartbeatIntervalMs);
  }

  // 发送心跳
  sendPing(): void {
    if (this.ws?.readyState === WebSocket.OPEN) {
      const pingData: PingRequestSerializer = {
        type: 'ping'
      };
      this.send(pingData);
    }
  }

  // 开始流式对话
  startStream(messageText: string, model?: string, role?: string): void {
    if (this.ws?.readyState !== WebSocket.OPEN) {
      console.error('WebSocket未连接');
      message.error('连接断开，请重试');
      return;
    }

    const data: StreamStartRequestSerializer = {
      type: 'start_stream',
      message: messageText,
      model,
      role
    };

    this.send(data);
  }

  // 停止流式对话
  stopStream(streamId: string): void {
    if (this.ws?.readyState !== WebSocket.OPEN) {
      console.error('WebSocket未连接');
      return;
    }

    const data: StreamStopRequestSerializer = {
      type: 'stop_stream',
      stream_id: streamId
    };

    this.send(data);
  }

  // 发送消息的通用方法
  private send(data: any): void {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(data));
    } else {
      console.error('WebSocket未连接，无法发送消息');
    }
  }

  // 获取连接状态
  get isConnected(): boolean {
    return this.ws?.readyState === WebSocket.OPEN;
  }

  // 获取连接状态描述
  get connectionState(): string {
    if (!this.ws) return 'DISCONNECTED';
    
    switch (this.ws.readyState) {
      case WebSocket.CONNECTING:
        return 'CONNECTING';
      case WebSocket.OPEN:
        return 'CONNECTED';
      case WebSocket.CLOSING:
        return 'CLOSING';
      case WebSocket.CLOSED:
        return 'CLOSED';
      default:
        return 'UNKNOWN';
    }
  }
}